use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;
use chrono::NaiveDate;

/**
 * 定义cell
*/
#[derive(Debug)]
pub enum CljCell {
    // (XXX) 需要计算的序列 例如： (add a b)
    //CljList {vs: Vec<CljCell>},
    CljList(Vec<Rc<CljCell>>),
    // '(XXX) 不需要计算的序列 例如： '(add a b)
    //List {vs: Vec<CljCell>},
    List(Vec<Rc<CljCell>>),
    // set
    //Set {vs: Vec<CljCell>},
    Set(Vec<Rc<CljCell>>),
    // hash_table
    HashTable(HashMap<Rc<CljCell>, Rc<CljCell>>),
    //HashTable(Box<dyn Any>),
    // ` 阻止() 表达式求值 例如：`(if ~test (list ~@body))
    QuoteList,
    QuoteListVs(Rc<CljCell>),
    // ' 阻止表达式求值 例如：'if
    Quote,
    // ' 阻止表达式求值 例如：'if 组装成一个新的 token
    QuoteVs(Rc<CljCell>),
    // ~ 求值表达式 例如： ~test
    Unquote,
    // ~ 求值表达式 例如： ~test 组装成一个新的 token
    UnquoteVs(Rc<CljCell>),
    // ~@ 对序列求值，并展开
    UnquoteList,
    UnquoteListVs(Rc<CljCell>),
    // &
    AndClj,
    // defmacro 宏
    Defmacro,
    // defn 方法
    Defn,
    // def 定义
    DefClj,
    // fn 匿名方法
    FnClj,
    // let
    LetClj,
    // cond
    Cond,
    // if
    IfClj,
    // first
    FirstClj,
    // last
    LastClj,
    // rest
    RestClj,
    // do
    DoClj,
    // loop
    LoopClj,
    // recur
    Recur,
    // conj
    Conj,
    // apply
    Apply,
    // map
    MapClj,
    // cons
    Cons,
    // reduce
    ReduceClj,
    // eval
    Eval,

    // 中括号
    BracketClj(Vec<Rc<CljCell>>),
    // 大括号
    BracesClj(Vec<Rc<CljCell>>),

    // 中括号
    LbracketClj,
    RbracketClj,
    // 大括号
    LbracesClj,
    RbracesClj,

    // 小括号
    LparenClj,
    RparenClj,

    // 标识符
    //Symbol {vs: String},
    Symbol(Rc<String>),

    // : 标识符
    //KeySymbol {vs: String},
    KeySymbol(Rc<String>),

    // 字符串
    //StringClj {vs: String},
    StringClj(Rc<String>),
    // 数字
    NumberClj (Rc<String>),
    // 布尔类型
    //BooleanClj {vs: bool},
    BooleanClj (bool),
    // 日期类型
    DateClj(Rc<NaiveDate>),
    // int
    //IntClj {vs: i32},
    IntClj (i32),
    // long
    //LongClj {vs: i64},
    LongClj (i64),
    // char
    CharClj,
    // short
    ShortClj,
    // byte
    ByteClj,
    // double
    //DoubleClj {vs: f64},
    DoubleClj (f64),
    // float
    FloatClj (f32),

    // 基础类型的函数
    // (string "吴大富")
    StringFunc,
    // 数字
    NumberFunc,
    // 布尔类型
    BooleanFunc,
    // 日期类型
    DateFunc,
    // int
    IntFunc,
    // long
    LongFunc,
    // char
    CharFunc,
    // short
    ShortFunc,
    // byte
    ByteFunc,
    // double
    DoubleFunc,
    // float
    FloatFunc,

    /**
     * 数学符号
     * */
    // + 加法
    Addition,
    // - 减法
    Subtraction,
    // * 乘法
    Multiplication,
    // / 除法
    Division,

    /**
     * 逻辑判断
     * */
    // not
    NotClj,
    // nil
    Nil,
    // is nil
    IsNil,
    // 和
    AndLgClj,
    // 或
    OrLgClj,
    // 等于
    EqualsLgClj,
    // 大于
    GreaterThanLgClj,
    // 小于
    LessThanLgClj,
    // 大于等于
    GreaterEqualsLgClj,
    // 小于等于
    LessEqualsLgClj,
    // else
    ElseClj,
    // println
    //PrintlnClj,

    /**
     * 特殊符号
     * */
    // #
    Sharp,
    // 百分号
    //Percent {vs_index: Vec<CljCell>, has_vs: bool},
    Percent (Option<Box<CljCell>>),
    // 匿名函数
    //Anonymous {vs: Vec<CljCell>},
    Anonymous (Vec<Rc<CljCell>>),

    // 表示这个 Cell 都为空
    Null
}

// impl Clone for CljCell {
//     fn clone(&self) -> Self {
//         match self {
//             // (XXX) 需要计算的序列 例如： (add a b)
//             CljCell::CljList {vs} => CljCell::CljList {vs: vs},
//             // '(XXX) 不需要计算的序列 例如： '(add a b)
//             List {vs: Vec<CljCell>},
//             // set
//             Set {vs: Vec<CljCell>},
//             // hash_table
//             HashTable(HashMap<CljCell, CljCell>),
//             //HashTable(Box<dyn Any>),
//             // ` 阻止() 表达式求值 例如：`(if ~test (list ~@body))
//             QuoteList,
//             // ' 阻止表达式求值 例如：'if
//             Quote,
//             // ~ 求值表达式 例如： ~test
//             Unquote,
//             // ~@ 对序列求值，并展开
//             UnquoteList,
//             // &
//             AndClj,
//             // defmacro 宏
//             Defmacro,
//             // defn 方法
//             Defn,
//             // def 定义
//             DefClj,
//             // fn 匿名方法
//             FnClj,
//             // let
//             LetClj,
//             // cond
//             Cond,
//             // if
//             IfClj,
//             // first
//             FirstClj,
//             // last
//             LastClj,
//             // rest
//             RestClj,
//             // do
//             DoClj,
//             // loop
//             LoopClj,
//             // recur
//             Recur,
//             // conj
//             Conj,
//             // apply
//             Apply,
//             // map
//             MapClj,
//             // cons
//             Cons,
//             // reduce
//             ReduceClj,
//             // eval
//             Eval,
//
//             // 中括号
//             BracketClj(Vec<CljCell>),
//             // 大括号
//             BracesClj(Vec<CljCell>),
//
//             // 中括号
//             LbracketClj,
//             RbracketClj,
//             // 大括号
//             LbracesClj,
//             RbracesClj,
//
//             // 小括号
//             LparenClj,
//             RparenClj,
//
//             // 标识符
//             Symbol {vs: String},
//
//             // : 标识符
//             KeySymbol {vs: String},
//
//             // 字符串
//             StringClj {vs: String},
//             // 数字
//             NumberClj (String),
//             // 布尔类型
//             BooleanClj {vs: bool},
//             // 日期类型
//             DateClj,
//             // int
//             IntClj {vs: i32},
//             // long
//             LongClj {vs: i64},
//             // char
//             CharClj,
//             // short
//             ShortClj,
//             // byte
//             ByteClj,
//             // double
//             DoubleClj {vs: f64},
//             // float
//             FloatClj,
//
//             // 基础类型的函数
//             // (string "吴大富")
//             StringFunc,
//             // 数字
//             NumberFunc,
//             // 布尔类型
//             BooleanFunc,
//             // 日期类型
//             DateFunc,
//             // int
//             IntFunc,
//             // long
//             LongFunc,
//             // char
//             CharFunc,
//             // short
//             ShortFunc,
//             // byte
//             ByteFunc,
//             // double
//             DoubleFunc,
//             // float
//             FloatFunc,
//
//             /**
//              * 数学符号
//              * */
//             // + 加法
//             Addition,
//             // - 减法
//             Subtraction,
//             // * 乘法
//             Multiplication,
//             // / 除法
//             Division,
//
//             /**
//              * 逻辑判断
//              * */
//             // not
//             NotClj,
//             // nil
//             Nil,
//             // is nil
//             IsNil,
//             // 和
//             AndLgClj,
//             // 或
//             OrLgClj,
//             // 等于
//             EqualsLgClj,
//             // 大于
//             GreaterThanLgClj,
//             // 小于
//             LessThanLgClj,
//             // 大于等于
//             GreaterEqualsLgClj,
//             // 小于等于
//             LessEqualsLgClj,
//             // else
//             ElseClj,
//             // println
//             PrintlnClj,
//
//             /**
//              * 特殊符号
//              * */
//             // #
//             Sharp,
//             // 百分号
//             Percent(Option<Box<CljCell>>),
//             // 匿名函数
//             Anonymous {vs: Vec<CljCell>},
//
//             // 表示这个 Cell 都为空
//             Null
//         }
//     }
// }

impl CljCell {
    pub fn to_string(&self) -> String {
        match self {
            CljCell::CljList (vs) => {
                let mut line = String::new();
                //line.push_str(&vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>().join(" "));
                let lst = vs.into_iter().map(|item| self.to_string()).collect::<Vec<String>>();
                line.push_str("(");
                for i in 0..lst.len() {
                    if i == lst.len() - 1 {
                        line.push_str(&lst[i]);
                    } else {
                        line.push_str(&lst[i]);
                        line.push_str(" ");
                    }
                }
                line.push_str(")");
                return line;
            },
            CljCell::List (vs) => {
                let mut line = String::new();
                //line.push_str(&vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>().join(" "));
                let lst = vs.into_iter().map(|item| self.to_string()).collect::<Vec<String>>();
                line.push_str("(");
                for i in 0..lst.len() {
                    if i == lst.len() - 1 {
                        line.push_str(&lst[i]);
                    } else {
                        line.push_str(&lst[i]);
                        line.push_str(" ");
                    }
                }
                line.push_str(")");
                return line;
            },
            CljCell::Set (vs) => {
                let mut line = String::new();
                //line.push_str(&vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>().join(" "));
                let lst = vs.into_iter().map(|item| self.to_string()).collect::<Vec<String>>();
                line.push_str("#{");
                for i in 0..lst.len() {
                    if i == lst.len() - 1 {
                        line.push_str(&lst[i]);
                    } else {
                        line.push_str(&lst[i]);
                        line.push_str(" ");
                    }
                }
                line.push_str("}");
                return line;
            },
            CljCell::Symbol (vs) => return vs.as_ref().clone(),
            CljCell::KeySymbol (vs) => return vs.as_ref().clone(),
            CljCell::DefClj => return String::from("def"),
            CljCell::LetClj => return String::from("let"),
            CljCell::Cond => return String::from("cond"),
            CljCell::Conj => return String::from("conj"),
            CljCell::Defn => return String::from("defn"),
            CljCell::FnClj => return String::from("fn"),
            CljCell::LastClj => return String::from("last"),
            CljCell::HashTable(vs) => {
                let mut line = String::new();
                line.push_str("{");
                let mut i = 0;
                for (key, value) in vs {
                    line.push_str(&key.to_string());
                    line.push_str(" ");
                    line.push_str(&value.to_string());
                    if i != vs.len() - 1 {
                        line.push_str(" ");
                        i += 1;
                    }
                }

                line.push_str("}");
                return line;
            },
            CljCell::Anonymous (vs) => {
                let mut line = String::new();
                line.push_str("#");
                for i in 0..vs.len() {
                    if i == vs.len() - 1 {
                        let mc = vs[i].clone();
                        match &*mc {
                            CljCell::Percent(my_ptr) => {
                                line.push_str("%");
                                line.push_str(&vs[i].to_string());
                            },
                            _ => {
                                line.push_str(&vs[i].to_string());
                            }
                        }
                        line.push_str(&vs[i].to_string());
                    } else {
                        let mc = vs[i].clone();
                        match &*mc {
                            CljCell::Percent(my_ptr) => {
                                line.push_str("%");
                                line.push_str(&vs[i].to_string());
                                line.push_str(" ");
                            },
                            _ => {
                                line.push_str(&vs[i].to_string());
                                line.push_str(" ");
                            }
                        }
                    }
                }
                line.push_str("}");
                return line;
            },
            CljCell::Percent(my_ptr) => {
                if my_ptr.is_none() == true {
                    return String::from("%");
                } else {
                    //let my_ptr1: Box<CljCell> = my_ptr;
                    let mut line = String::new();
                    line.push_str("%");
                    line.push_str(&my_ptr.as_ref().unwrap().to_string());
                    //line.push_str(&vs_index[0].to_string());
                    return line;
                }
            },
            CljCell::LongClj (vs) => return vs.to_string(),
            CljCell::IntClj(vs) => return vs.to_string(),
            CljCell::DoubleClj(vs) => return vs.to_string(),
            CljCell::FloatClj(vs) => return vs.to_string(),
            CljCell::Recur => return String::from("recur"),
            CljCell::Apply => return String::from("apply"),
            CljCell::MapClj => return String::from("map"),
            CljCell::Cons => return String::from("cons"),
            CljCell::ReduceClj => return String::from("reduce"),
            CljCell::Eval => return String::from("eval"),
            CljCell::RestClj => return String::from("rest"),
            CljCell::FirstClj => return String::from("first"),
            CljCell::Quote => return String::from("'"),
            CljCell::BracesClj(lst) => {
                let mut line = String::new();
                line.push_str("{");
                for i in 0..lst.len() {
                    if i == lst.len() - 1 {
                        line.push_str(&lst[i].to_string());
                    } else {
                        line.push_str(&lst[i].to_string());
                        line.push_str(" ");
                    }
                }
                line.push_str("}");
                return line;
            },
            CljCell::DoClj => return String::from("do"),
            CljCell::IfClj => return String::from("if"),
            CljCell::AndClj => return String::from("&"),
            CljCell::BracketClj(lst) => {
                let mut line = String::new();
                line.push_str("[");
                for i in 0..lst.len() {
                    if i == lst.len() - 1 {
                        line.push_str(&lst[i].to_string());
                    } else {
                        line.push_str(&lst[i].to_string());
                        line.push_str(" ");
                    }
                }
                line.push_str("]");
                return line;
            },
            CljCell::Unquote => return String::from("~"),
            CljCell::Defmacro => return String::from("defmacro"),
            CljCell::NumberClj(num) => return num.to_string(),
            CljCell::QuoteList => return String::from("`"),
            CljCell::StringClj (vs) => return vs.as_ref().clone(),
            CljCell::UnquoteList => return String::from("~@"),
            CljCell::Addition => return String::from("+"),
            CljCell::Subtraction => return String::from("-"),
            CljCell::Multiplication => return String::from("*"),
            CljCell::Division => return String::from("/"),
            CljCell::StringFunc => return String::from("string"),
            CljCell::BooleanFunc => return String::from("bool"),
            CljCell::DateFunc => return String::from("date"),
            CljCell::IntFunc => return String::from("int"),
            CljCell::LongFunc => return String::from("long"),
            CljCell::CharFunc => return String::from("char"),
            CljCell::ShortFunc => return String::from("short"),
            CljCell::ByteFunc => return String::from("byte"),
            CljCell::DoubleFunc => return String::from("double"),
            CljCell::FloatFunc => return String::from("float"),
            CljCell::AndLgClj => return String::from("and"),
            CljCell::OrLgClj => return String::from("or"),
            CljCell::EqualsLgClj => return String::from("="),
            CljCell::GreaterThanLgClj => return String::from(">"),
            CljCell::LessThanLgClj => return String::from("<"),
            CljCell::GreaterEqualsLgClj => return String::from(">="),
            CljCell::LessEqualsLgClj => return String::from("<="),
            CljCell::ElseClj => return String::from(":else"),
            CljCell::LbracketClj => return String::from("["),
            CljCell::RbracketClj => return String::from("]"),
            CljCell::LbracesClj => return String::from("{"),
            CljCell::RbracesClj => return String::from("}"),
            CljCell::LparenClj => return String::from("("),
            CljCell::RparenClj => return String::from(")"),
            CljCell::IsNil => return String::from("nil?"),
            CljCell::NotClj => return String::from("not"),
            CljCell::BooleanClj (vs) => {
                if vs == &true {
                    return String::from("true");
                } else {
                    return String::from("false");
                }
            },
            //CljCell::PrintlnClj => return String::from("println"),
            _ => return String::from(""),
        }
        //return String::from("");
    }
}

// pub fn to_string(s: &CljCell) -> String {
//     match s {
//         CljCell::CljList {vs} => {
//             let mut line = String::new();
//             //line.push_str(&vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>().join(" "));
//             let lst = vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>();
//             line.push_str("(");
//             for i in 0..lst.len() {
//                 if i == lst.len() - 1 {
//                     line.push_str(&lst[i]);
//                 } else {
//                     line.push_str(&lst[i]);
//                     line.push_str(" ");
//                 }
//             }
//             line.push_str(")");
//             return line;
//         },
//         CljCell::List {vs} => {
//             let mut line = String::new();
//             //line.push_str(&vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>().join(" "));
//             let lst = vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>();
//             line.push_str("(");
//             for i in 0..lst.len() {
//                 if i == lst.len() - 1 {
//                     line.push_str(&lst[i]);
//                 } else {
//                     line.push_str(&lst[i]);
//                     line.push_str(" ");
//                 }
//             }
//             line.push_str(")");
//             return line;
//         },
//         CljCell::Set {vs} => {
//             let mut line = String::new();
//             //line.push_str(&vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>().join(" "));
//             let lst = vs.into_iter().map(|item| to_string(item)).collect::<Vec<String>>();
//             line.push_str("#{");
//             for i in 0..lst.len() {
//                 if i == lst.len() - 1 {
//                     line.push_str(&lst[i]);
//                 } else {
//                     line.push_str(&lst[i]);
//                     line.push_str(" ");
//                 }
//             }
//             line.push_str("}");
//             return line;
//         },
//         CljCell::Symbol {vs} => return String::from(vs),
//         CljCell::KeySymbol {vs} => return String::from(vs),
//         CljCell::DefClj => return String::from("def"),
//         CljCell::LetClj => return String::from("let"),
//         CljCell::Cond => return String::from("cond"),
//         CljCell::Conj => return String::from("conj"),
//         CljCell::Defn => return String::from("defn"),
//         CljCell::FnClj => return String::from("fn"),
//         CljCell::LastClj => return String::from("last"),
//         CljCell::HashTable(vs) => {
//             let mut line = String::new();
//             line.push_str("{");
//             let mut i = 0;
//             for (key, value) in vs {
//                 line.push_str(&to_string(key));
//                 line.push_str(" ");
//                 line.push_str(&to_string(value));
//                 if i != vs.len() - 1 {
//                     line.push_str(" ");
//                     i += 1;
//                 }
//             }
//
//             line.push_str("}");
//             return line;
//         },
//         CljCell::Anonymous {vs} => {
//             let mut line = String::new();
//             line.push_str("#");
//             for i in 0..vs.len() {
//                 if i == vs.len() - 1 {
//                     match &vs[i] {
//                         CljCell::Percent(my_box) => {
//                             line.push_str("%");
//                             line.push_str(&to_string(&vs[i]));
//                         },
//                         _ => {
//                             line.push_str(&to_string(&vs[i]));
//                         }
//                     }
//                     line.push_str(&to_string(&vs[i]));
//                 } else {
//                     match &vs[i] {
//                         CljCell::Percent(my_box) => {
//                             line.push_str("%");
//                             line.push_str(&to_string(&vs[i]));
//                             line.push_str(" ");
//                         },
//                         _ => {
//                             line.push_str(&to_string(&vs[i]));
//                             line.push_str(" ");
//                         }
//                     }
//                 }
//             }
//             line.push_str("}");
//             return line;
//         },
//         CljCell::Percent(my_ptr) => {
//             if my_ptr.is_none() {
//                 return String::from("%");
//             } else {
//                 //let my_ptr1: Box<CljCell> = my_ptr;
//                 let mut line = String::new();
//                 line.push_str("%");
//                 line.push_str(&to_string(&my_ptr.as_ref().unwrap()));
//                 return line;
//             }
//         },
//         CljCell::LongClj {vs} => return String::from("loop"),
//         CljCell::Recur => return String::from("recur"),
//         CljCell::Apply => return String::from("apply"),
//         CljCell::MapClj => return String::from("map"),
//         CljCell::Cons => return String::from("cons"),
//         CljCell::ReduceClj => return String::from("reduce"),
//         CljCell::Eval => return String::from("eval"),
//         CljCell::RestClj => return String::from("rest"),
//         CljCell::FirstClj => return String::from("first"),
//         CljCell::Quote => return String::from("'"),
//         CljCell::BracesClj(lst) => {
//             let mut line = String::new();
//             line.push_str("{");
//             for i in 0..lst.len() {
//                 if i == lst.len() - 1 {
//                     line.push_str(&to_string(&lst[i]));
//                 } else {
//                     line.push_str(&to_string(&lst[i]));
//                     line.push_str(" ");
//                 }
//             }
//             line.push_str("}");
//             return line;
//         },
//         CljCell::DoClj => return String::from("do"),
//         CljCell::IfClj => return String::from("if"),
//         CljCell::AndClj => return String::from("&"),
//         CljCell::BracketClj(lst) => {
//             let mut line = String::new();
//             line.push_str("[");
//             for i in 0..lst.len() {
//                 if i == lst.len() - 1 {
//                     line.push_str(&to_string(&lst[i]));
//                 } else {
//                     line.push_str(&to_string(&lst[i]));
//                     line.push_str(" ");
//                 }
//             }
//             line.push_str("]");
//             return line;
//         },
//         CljCell::Unquote => return String::from("~"),
//         CljCell::Defmacro => return String::from("defmacro"),
//         CljCell::NumberClj(num) => return String::from(num),
//         CljCell::QuoteList => return String::from("`"),
//         CljCell::StringClj {vs} => return String::from(vs),
//         CljCell::UnquoteList => return String::from("~@"),
//         CljCell::Addition => return String::from("+"),
//         CljCell::Subtraction => return String::from("-"),
//         CljCell::Multiplication => return String::from("*"),
//         CljCell::Division => return String::from("/"),
//         CljCell::StringFunc => return String::from("string"),
//         CljCell::BooleanFunc => return String::from("bool"),
//         CljCell::DateFunc => return String::from("date"),
//         CljCell::IntFunc => return String::from("int"),
//         CljCell::LongFunc => return String::from("long"),
//         CljCell::CharFunc => return String::from("char"),
//         CljCell::ShortFunc => return String::from("short"),
//         CljCell::ByteFunc => return String::from("byte"),
//         CljCell::DoubleFunc => return String::from("double"),
//         CljCell::FloatFunc => return String::from("float"),
//         CljCell::AndLgClj => return String::from("and"),
//         CljCell::OrLgClj => return String::from("or"),
//         CljCell::EqualsLgClj => return String::from("="),
//         CljCell::GreaterThanLgClj => return String::from(">"),
//         CljCell::LessThanLgClj => return String::from("<"),
//         CljCell::GreaterEqualsLgClj => return String::from(">="),
//         CljCell::LessEqualsLgClj => return String::from("<="),
//         CljCell::ElseClj => return String::from(":else"),
//         CljCell::LbracketClj => return String::from("["),
//         CljCell::RbracketClj => return String::from("]"),
//         CljCell::LbracesClj => return String::from("{"),
//         CljCell::RbracesClj => return String::from("}"),
//         CljCell::LparenClj => return String::from("("),
//         CljCell::RparenClj => return String::from(")"),
//         CljCell::IsNil => return String::from("nil?"),
//         CljCell::NotClj => return String::from("not"),
//         CljCell::BooleanClj {vs} => {
//             if vs == &true {
//                 return String::from("true");
//             } else {
//                 return String::from("false");
//             }
//         },
//         CljCell::PrintlnClj => return String::from("println"),
//         _ => return String::from(""),
//     }
//     return String::from("");
// }

impl fmt::Display for CljCell {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        //write!(f, "{}", to_string(&self))
        write!(f, "{}", self.to_string())
    }
}

pub fn add(a:i32, b:i32) -> i32 {
    a + b
}













































